package top.soft.windows;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedHashMap;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

import top.soft.bean.User;
import top.soft.util.CommonData;
import top.soft.util.NetWork;
import top.soft.util.Request;
import top.soft.util.Response;
import top.soft.util.WebSocketClientImpl;

/**
 * @ClassName: LoginWindow
 * @Author: Amosen
 * @Since: 2021/4/12
 */
public class LoginWindow extends JFrame {

	private JPanel jPanelCenter, jPanelSouth;

	private JTextField account;

	private JPasswordField password;

	private JButton loginButton, registerButton;

	public LoginWindow() {
		init();
	}

	private void init() {
		this.setTitle(CommonData.WINDOW_TITLE);

		jPanelCenter = new JPanel();
		jPanelCenter.setLayout(new GridLayout(3, 2));
		jPanelCenter.add(new JLabel(CommonData.LOGIN_USERNAME));
		account = new JTextField();
		jPanelCenter.add(account);
		jPanelCenter.add(new JLabel(CommonData.LOGIN_PASSWORD));
		password = new JPasswordField();

		password.addKeyListener(new LoginListener());
		account.addKeyListener(new LoginListener());

		jPanelCenter.add(password);

		jPanelCenter.add(new JLabel("----------------------------------------------"));
		jPanelCenter.add(new JLabel("----------------------------------------------"));

		jPanelSouth = new JPanel();
		jPanelSouth.setLayout(new GridLayout(1, 2));
		loginButton = new JButton(CommonData.LOGIN_BTN);
		loginButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				doLogin();
			}
		});

		jPanelSouth.add(loginButton);

		registerButton = new JButton(CommonData.REGISTER_BTN);
		registerButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				doRegister();
			}
		});

		jPanelSouth.add(registerButton);

		this.add(jPanelCenter, BorderLayout.CENTER);
		this.add(jPanelSouth, BorderLayout.SOUTH);

		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.setBounds(450, 250, 375, 140);
		this.setResizable(false);
		this.setVisible(true);
		account.requestFocus();
	}

	private class LoginListener extends KeyAdapter {

		@Override
		public void keyPressed(KeyEvent e) {
			super.keyPressed(e);
			if (e.getKeyCode() == KeyEvent.VK_ENTER) {
				doLogin();
			}
		}
	}

	private boolean check() {
		String inputAccount = account.getText();
		char[] rawPasswordChar = this.password.getPassword();
		if (inputAccount == null) {
			account.requestFocus();
			return false;
		}
		if (rawPasswordChar == null) {
			password.requestFocus();
			return false;
		}
		if (inputAccount.trim().length() == 0) {
			account.requestFocus();
			return false;
		}
		if (String.valueOf(rawPasswordChar).trim().length() == 0) {
			password.requestFocus();
			return false;
		}
		return true;
	}

	private void doLogin() {
		// 检查 account 或者 password 中的内容是否为空，为空获取焦点
		boolean canLogin = check();
		if (!canLogin) {
			return;
		}
		String inputAccount = account.getText();
		char[] rawPasswordChar = this.password.getPassword();
		// 全部不为空，获取account和password的字符串表示，发送给服务器校验
		String inputPassword = String.valueOf(rawPasswordChar);
		// 封装为Request对象
		Request loginRequest = new Request(CommonData.LOGIN_PATH, Request.GET);
		loginRequest.addData("account", inputAccount);
		loginRequest.addData("password", inputPassword);
		Response loginResponse = NetWork.doGet(loginRequest);
		if (loginResponse == null) {
			JOptionPane.showMessageDialog(null, "网络连接失败！");
		} else {
			if (loginResponse.getCode() != 200) {
				password.setText("");
				JOptionPane.showMessageDialog(null, "用户名或密码错误！");
			} else {
				// 登录成功，将数据封装为User对象放在CommonData中，设置登录成功，进入主界面
				try {
					LinkedHashMap<String, Object> userMaps = (LinkedHashMap<String, Object>) loginResponse.getData()
							.get("user");
					String account = (String) userMaps.get("account");
					Integer auth = (Integer) userMaps.get("auth");
					User loginUser = new User(account, auth);
					CommonData.setIsLogin(true);
					CommonData.setUser(loginUser);
				} catch (Exception e) {
					e.printStackTrace();
					JOptionPane.showMessageDialog(null, "程序发生异常！错误代码：" + CommonData.CLASS_CAST_EXCEPTION_CODE);
				}
				// 尝试开启WebSocket连接
				WebSocketClientImpl wsc;
				try {
					wsc = new WebSocketClientImpl(new URI(CommonData.WEBSOCKET_URI + "/" + inputAccount));
					if (!wsc.isOpen()) {
						JOptionPane.showMessageDialog(null, "尝试连接服务器失败！");
					} else {
						// 连接成功，将客户端保存
						CommonData.setWebSocketClient(wsc);
						// 进入主程序
						new MainWindow(this);
					}
				} catch (URISyntaxException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}

			}
		}
	}

	private void doRegister() {
		if (!check()) {
			return;
		} else {
			// 获取account和password
			String account = this.account.getText();
			String password = String.valueOf(this.password.getPassword());
			// 封装为Request对象
			Request registerRequest = new Request(CommonData.REGISTER_PATH, Request.GET);
			registerRequest.addData("account", account).addData("password", password);
			// 发起请求
			Response response = NetWork.doGet(registerRequest);
			if (response == null) {
				JOptionPane.showMessageDialog(null, "登录失败，请检查网络后重试！");
				return;
			} else {
				if (response.getCode() != 200) {
					JOptionPane.showMessageDialog(null, "注册失败！");
					return;
				} else {
					// 注册成功，将注册好的数据封装为User对象，保存在CommonData中，设置登录成功，进入主界面

					// TODO: 注册WebSocket客户端
					// 尝试开启WebSocket连接
					WebSocketClientImpl wsc;
					try {
						wsc = new WebSocketClientImpl(new URI(CommonData.WEBSOCKET_URI + "/" + account));
						if (!wsc.isOpen()) {
							JOptionPane.showMessageDialog(null, "尝试连接服务器失败！");
						} else {
							// 连接成功，将客户端保存
							CommonData.setWebSocketClient(wsc);
							// 进入主程序
							new MainWindow(this);
						}
					} catch (URISyntaxException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

					User loginUser = new User(account, CommonData.COMMON_AUTH);
					CommonData.setUser(loginUser);
					CommonData.setIsLogin(true);
					new MainWindow(this);
				}
			}
		}
	}
}
